<?php

declare(strict_types=1);

namespace App\CustHub\Service;


use App\Common\Constants\StorageModeConstants;
use App\Common\Helpers\CommonUpload;
use App\Common\Helpers\QrCode;
use App\Common\Redis\RedisCluster;
use App\Common\Robot\Robot;
use App\Common\Service\ShortChainService;
use App\CustHub\Amqp\Producers\SendRecordProducers;
use App\CustHub\Constants\ContactTaskCenterTyperConstants;
use App\CustHub\Constants\OperatorLogConstants;
use App\CustHub\Constants\SendConfigConstants;
use App\CustHub\Dto\AddContactWayDto;
use App\CustHub\Dto\ContactTcContentDto;
use App\CustHub\Dto\OperationLogDto;
use App\CustHub\Dto\SendRecordProducersDto;
use App\CustHub\Event\ChOperationLog;
use App\CustHub\Helpers\ImageHelp;
use App\CustHub\Helpers\TagReplacer;
use App\CustHub\Helpers\WxDownload;
use App\CustHub\Mapper\ChChannelCodeChangeLogMapper;
use App\CustHub\Mapper\ChChannelCodeMapper;
use App\CustHub\Mapper\ChChannelCodeRecordMapper;
use App\CustHub\Mapper\ChChannelCodeRobotAddNumberMapper;
use App\CustHub\Mapper\ChContactMapper;
use App\CustHub\Mapper\ChCorpMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Model\ChChannelCode;
use App\CustHub\Model\ChContact;
use App\CustHub\Model\ChRobot;
use App\Exception\BusinessException;
use App\Robot\Dto\RobotMsgDto;
use App\Robot\Job\SendRobotMsgDelayedJob;
use App\Robot\Service\RobotApiService;
use App\Setting\Service\SettingConfigService;
use Carbon\Carbon;
use DateTimeInterface;
use Hyperf\Amqp\Producer;
use Hyperf\Collection\Arr;
use Hyperf\Config\Annotation\Value;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Paginator\LengthAwarePaginator;
use Hyperf\Redis\Redis;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use Mine\MineCollection;
use Mine\MineModel;
use Mine\MineResponse;
use Nette\Utils\Random;
use Psr\Http\Message\ResponseInterface;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\data_get;
use function Hyperf\Collection\data_set;
use function Hyperf\Coroutine\co;

class ChChannelCodeService extends AbstractService
{
    #[Inject]
    protected ChChannelCodeRecordMapper $codeRecordMapper;

    #[Inject]
    protected ChRobotMapper $robotMapper;

    #[Inject]
    protected ChChannelCodeChangeLogMapper $changeLogMapper;


    #[Inject]
    protected ChChannelCodeRobotAddNumberMapper $robotAddNumberMapper;

    #[Inject]
    protected Redis $redis;

    #[Value('cache.default.prefix')]
    protected string $prefix;
    public $cachePrefix = 'ch_channel_code_cache:';

    public $mapper;

    // 定义字段处理配置（可扩展）
    private array $configHandlers = [
        'direct' => [ // 直接处理robot_ids的字段
            'paths' => [
                'robot_ids',
                'spare_robot_ids'
            ]
        ],
        'nested' => [ // 需要处理嵌套结构的字段
            'paths' => [
                'time_segment_cfg.*',
                'daily_add_friend_cfg.*',
                'special_member_greeting_cfg.*'
            ]
        ]
    ];


    public function __construct(ChChannelCodeMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function loopUpChannelCode()
    {
        $this->mapper->model::query()->whereNotNull('next_refresh_time')->where('next_refresh_time', '<=', Carbon::now()->getTimestamp())
            ->chunkById(100, function ($codeList){
                foreach ($codeList as $code){
                    co(function () use ($code) {
                        $enableRobotInfo=$this->getEnableRobotInfo($code,Carbon::now());
                        if (empty($enableRobotInfo['robotIds'])) {
                            return;
                        }
                        $this->upContactWay($enableRobotInfo['robotIds'],$code);
                        $this->mapper->update($code->id,[
                            'next_refresh_time'=>$enableRobotInfo['nextRefreshTime']
                        ]);
                    });
                }

            });
    }

    /**
     * 渠道码扫码加好友后逻辑
     * @return void
     */
    public function afterScanCode(array $data, ChRobot $robotInfo, $info): mixed
    {
        var_dump('渠道码扫码加好友后逻辑开始');
        try {
            $userId = $data['sender'];
            //查询客户详情
            $corpInfo = container()->get(ChCorpMapper::class)->findById($robotInfo->corp_id);
            if (empty($corpInfo->auth_corp_id)) {
                return false;
            }
            $OpenWorkService = new OpenWorkService($corpInfo->auth_corp_id);
            $external_userid = container()->get(ChContactService::class)->getExternalUserid($robotInfo, $data['sender']);
            if (empty($external_userid)) {
                throw new NormalStatusException('获取external_userid失败');
            }
            $contactDetail = $OpenWorkService->getExternalContactDetail($external_userid);

            if (empty($contactDetail['follow_user'][0]['state'])) {
                return false;
            }
            $stateStr = $contactDetail['follow_user'][0]['state'];
            var_dump($stateStr);
            parse_str($stateStr, $stateStrArray);
            if (empty($stateStrArray['type']) && $stateStrArray['type'] != 1) {
                return false;
            }
            $codeId = $stateStrArray['code'];
        } catch (\Exception $e) {
            logger()->info("渠道码扫码获取用户信息错误:" . $e->getMessage());
            return false;
        }
        $code = $this->mapper->findById($codeId);
        //自动备注
        if ($code->auto_remark) {
            $service = make(Robot::class, [$robotInfo->server_id, $robotInfo->uuid])->gateway();
            $nickname = $contactDetail['external_contact']['name'];
            $remark_content = $code->remark_content;
            if (!empty($nickname) && str_contains($remark_content, '{昵称}')) {
                $remark_content = str_replace("{昵称}", base64_decode($nickname), $remark_content);
            }
            $service->updateWxContact((string)$userId, $remark_content, '', '', [], []);
        }
        //发送欢迎语
        if ($code->greeting_switch) {

            while (true) {
                try {
                    //指定成员欢迎语
                    if ($code->special_member_greeting) {
                        $special_member_greeting_cf = $code->special_member_greeting_cfg;
                        foreach ($special_member_greeting_cf as $item) {
                            if (in_array($robotInfo->id, $item['robot_ids'])) {
                                $content = $item['greeting'];
                                break;
                            }
                        }
                        break;
                    }
                    //分时段欢迎语
                    if ($code->time_segment_greeting) {
                        $time_segment_greeting_cfg = $code->time_segment_greeting_cfg;
                        $currentWeekDay = Carbon::now()->format('N');
                        $currentTime = Carbon::now()->format('H:i');
                        foreach ($time_segment_greeting_cfg as $item) {
                            // 星期匹配检查
                            if (!in_array($currentWeekDay, $item['week'] ?? [])) {
                                continue;
                            }

                            // 时间段处理（支持跨天）
                            $start = Carbon::parse($item['time'][0])->format('H:i');
                            $end = Carbon::parse($item['time'][1])->format('H:i');
                            $timeCondition = ($start > $end)
                                ? ($currentTime >= $start || $currentTime <= $end)
                                : ($currentTime >= $start && $currentTime <= $end);

                            if ($timeCondition) {
                                $content = $item['greeting'];
                                break;
                            }
                        }
                        break;
                    }
                    //默认欢迎语
                    //var_dump('默认欢迎语'.$code->default_greeting_cfg);
                    if (!empty($code->default_greeting_cfg)) {
                        $default_greeting_cfg = $code->default_greeting_cfg;
                        $content = $default_greeting_cfg;
                        break;
                    }
                    break;
                } catch (\Exception $e) {
                    break;
                }

            }
        }
        if (!empty($content)) {
            $msgData = new RobotMsgDto();
            $msgData->setMsgType('text')
                ->setContent($content[0]['content'])
                ->setToId($data['sender'])
                ->setServerId($robotInfo->server_id)
                ->setUuid($robotInfo->uuid);

            //消息发送服务
            $result = make(\App\Robot\Service\RobotMessageService::class, [$msgData])->sendMessage();
        }
        //更新codeId
        container()->get(ChContactMapper::class)->update($info->id, [
            'channel_code_id' => $codeId,
            'external_userid' => $external_userid,
        ]);
        //统计信息
        try {
            $isExist = ChContact::query()->where('user_id', $userId)->where('robot_id', $robotInfo->id)->exists();
            $this->addTask($robotInfo->id, $info->id, $code, $isExist);
            $this->addTagsAndRemark($info, $code);
        } catch (\Exception $e) {
            var_dump('channelCodeService error' . $e->getMessage());
            logger()->error("channelCodeService error", [$e]);
        }

        return true;
    }

    public function reset()
    {
        $this->robotAddNumberMapper->model::query()->update(['add_number' => 0]);
    }

    /**
     * 获取当前的机器人id和下次更新时间
     * @param $code
     * @return array
     */
    public function getEnableRobotInfo($code, Carbon $datetime)
    {
        $robotIds = [];
        $nextRefreshTime = null;
        switch ((int)$code->display_mode) {
            case 0:
                $robotIds = data_get($code->all_day_display_cfg, 'robot_ids', []);
                break;
            case 1:
                $currentWeekDay = (int)$datetime->format('N');
                $currentTime = $datetime->format('H:i');
                $isWorkDay = false;
                $isWorkTime = false;
                foreach (data_get($code, 'time_segment_cfg', []) as $segment) {
                    // 星期匹配检查
                    $isWorkDay = true;
                    if (in_array($currentWeekDay, $segment['week'] ?? [])) {
                        //当前是工作时间,查找下一次休息时间
                        // 时间段处理（支持跨天）
                        $start = Carbon::parse($segment['time'][0])->format('H:i');
                        $end = Carbon::parse($segment['time'][1])->format('H:i');
                        if ($start > $end) {
                            //跨天
                            if ($currentTime >= $start) {
                                $isWorkTime=true;
                                $robotIds = $segment['robot_ids'];
                                $nextRefreshTime = strtotime($datetime->addDays(1)->format('Y-m-d') . " " . $end) + 60;
                                break;
                            } else if ($currentTime <= $end) {
                                $isWorkTime=true;
                                $robotIds = $segment['robot_ids'];
                                $nextRefreshTime = strtotime($datetime->format('Y-m-d') . " " . $end) + 60;
                                break;
                            }
                        } else {
                            //不跨天
                            if ($currentTime >= $start && $currentTime <= $end) {
                                $isWorkTime=true;
                                $robotIds = $segment['robot_ids'];
                                $nextRefreshTime = strtotime($datetime->format('Y-m-d') . " " . $end) + 60;
                                break;
                            }
                        }
                        break;
                    }
                }
                if($isWorkDay && !$isWorkTime){
                    $robotIds = $code->spare_robot_ids['robot_ids'];
                    foreach (data_get($code, 'time_segment_cfg', []) as $segment) {
                        $start = Carbon::parse($segment['time'][0])->format('H:i');
                        $end = Carbon::parse($segment['time'][1])->format('H:i');
                        if($currentTime < $start){
                            $nextRefreshTime = strtotime($datetime->format('Y-m-d') . " " . $start) + 60;
                        }
                    }
                    empty($nextRefreshTime) && $nextRefreshTime = $datetime->endOfDay()->getTimestamp() + 60;
                }
                if (!$isWorkDay) {
                    //当天不在工作时间，找下次工作时间
                    $robotIds = $code->spare_robot_ids['robot_ids'];
                    //往后查7天
                    for ($i = 1; $i <= 7; $i++) {
                        $nextWeekDay = $datetime->copy()->addDays($i);
                        $result = $this->getRobotInfoByWeekDay($code, (int)$nextWeekDay->format('N'), $nextWeekDay);
                        if ($result) {
                            $nextRefreshTime = $result['nextRefreshTime'];
                            break;
                        }
                    }
                }
                break;
        }
        logger()->info('刷新code:'.$code->id."刷新信息".json_encode(['robotIds' => $robotIds, 'nextRefreshTime' => $nextRefreshTime]));
        return ['robotIds' => $robotIds, 'nextRefreshTime' => $nextRefreshTime];
    }

    public function getRobotInfoByWeekDay($code, $weekDay, $datetime)
    {
        var_dump($weekDay);
        foreach (data_get($code, 'time_segment_cfg', []) as $segment) {
            if (in_array($weekDay, $segment['week'] ?? [])) {
                // 时间段处理（支持跨天）
                $start = Carbon::parse($segment['time'][0])->format('H:i');
                $end = Carbon::parse($segment['time'][1])->format('H:i');
                $nextRefreshTime = strtotime($datetime->format('Y-m-d') . " " . $start) + 60;
                //$robotIds = $segment['robot_ids'];
                return ['nextRefreshTime' => $nextRefreshTime];
            }
        }
        return false;
    }

    /**
     * 落地页二维码信息
     * @param mixed $codeId
     */
    public function codeInfo(array $params)
    {
        $codeId = data_get($params, 'chain_code', 0);
        $code = $this->mapper->findById($codeId);
        if (empty($code)) {
            throw new NormalStatusException('code不存在');
        }
        // 1. 获取可执行的机器人
        $allRobotIds = match ((int)$code->display_mode) {
            0 => data_get($code->all_day_display_cfg, 'robot_ids', []),
            1 => $this->getTimeSegmentRobots($code, Carbon::now()),
            default => []
        };
        if (empty($allRobotIds)) {
            throw new NormalStatusException('未匹配到二维码信息');
        }
        //2.获取机器人每日添加数
        $robotAddNumbers = $this->robotAddNumberMapper->model::query()
            ->whereIn('robot_id', $allRobotIds)
            ->pluck('add_number', 'robot_id')
            ->toArray();

        // 3. 实时计算并匹配
        $now = Carbon::now();
        $enableRobotIds = $this->calculateEnableRobots($code, $now, $robotAddNumbers);
        $robotId = $enableRobotIds[array_rand($enableRobotIds)];
        //4.根据机器人获取活码信息
        $qrCode = [
            'qr_code' => $this->getContactWay($robotId, $code),
            'chain_type' => 1
        ];
        $qrCode['activity_desc'] = '';
        $qrCode['activity_title'] = '';
        //长按引导提示
        $qrCode['scan_tips'] = 1;
        //安全认证标识
        $qrCode['is_security'] = 1;
        $qrCode['wechat_qrcode'] = '';
        $qrCode['contact_number'] = '';
        $qrCode['is_technical_support'] = 0;
        return $qrCode;
    }

    public function getChannelCodeList(array $params): array
    {
        $uid = (int)($params['uid'] ?? 0);
        $pageSize = (int)($params['page_size'] ?? MineModel::PAGE_SIZE);

        $query = $this->mapper->model::query()
            ->select([
                'ch_channel_code.id',
                'ch_channel_code.auto_tags',
                'ch_channel_code.channel_name',
                'ch_channel_code.created_at',
                'ch_channel_code.code',
                'ch_channel_code.render_url',
                'ch_channel_code.display_mode',
                'ch_channel_code.all_day_display_cfg',
                'ch_channel_code.time_segment_cfg',
                'a.nickname as user_name',
            ])
            ->leftJoin('ch_user as a', 'ch_channel_code.uid', '=', 'a.id')
            ->where('ch_channel_code.uid', $uid)
            ->when(isset($params['channel_name']), function ($query) use ($params) {
                $query->where('ch_channel_code.channel_name', 'like', '%' . $params['channel_name'] . '%');
            })
            ->when(isset($params['time_range']), function ($query) use ($params) {
                $timeRange = explode(',', $params['time_range']);
                $start = Carbon::parse($timeRange[0])->startOfDay();
                $end = Carbon::parse($timeRange[1])->endOfDay();
                $query->whereBetween('ch_channel_code.created_at', [$start, $end]);
            })
            ->when(isset($params['tag_ids']), function ($query) use ($params) {
                $tagIds = explode(',', $params['tag_ids']);
                $query->where(function ($q) use ($tagIds) {
                    foreach ($tagIds as $tagId) {
                        $q->orWhere(function ($subQuery) use ($tagId) {
                            $subQuery->whereJsonContains('auto_tags->tags->corp_tags', ['id' => $tagId])
                                ->orWhereJsonContains('auto_tags->tags->smart_tags', ['id' => (int)$tagId]);
                        });
                    }
                });
            });

        // 2. 分页获取结果
        $paginator = $query->paginate($pageSize);
        $items = $paginator->items();

        // 3. 获取所有code_id用于统计查询,获取机器人信息
        $codeIds = collect($items)->pluck('id')->filter()->unique()->toArray();
        $robotAssignments = [];
        foreach ($codeIds as $codeId) {
            $robotIds = $this->getEnableRobotByCodeId($codeId);
            $robotAssignments[$codeId] = $this->getRobotData($robotIds);
        }

        // 4. 获取统计数据
        $statistics = [];
        if (!empty($codeIds)) {
            $statisticsCollection = $this->codeRecordMapper->getCodeStatisticsByUid([
                'code_ids' => $codeIds,
                'uid' => $uid
            ]);

            // 遍历 MineCollection 并将数据整理成以 code_id 为键的数组
            foreach ($statisticsCollection as $statistic) {
                $codeId = $statistic->code_id;
                $statistics[$codeId] = [
                    'total_count' => $statistic->total_count,
                    'weekly_count' => $statistic->weekly_count,
                    'daily_count' => $statistic->daily_count
                ];
            }
        }

        // 5. 合并统计数据到列表
        $resultItems = array_map(function ($item) use ($statistics, $robotAssignments) {
            $codeId = $item->id;
            $item->statistics = $statistics[$codeId] ?? [
                'total_count' => 0,
                'weekly_count' => 0,
                'daily_count' => 0
            ];
            // 注入机器人信息
            $allRobotIds = match ((int)$item->display_mode) {
                0 => data_get($item->all_day_display_cfg, 'robot_ids', []),
                1 => $this->getAllTimeSegmentRobots($item, Carbon::now()),
                default => []
            };
            $item->selected_robot = $this->getRobotData($allRobotIds);
            return $item;
        }, $items);

        // 6. 返回分页结果
        return $this->mapper->setPaginate(
            new LengthAwarePaginator(
                $resultItems,
                $paginator->total(),
                $paginator->perPage(),
                $paginator->currentPage(),
                ['path' => LengthAwarePaginator::resolveCurrentPath()]
            )
        );
    }

    public function saveChannelCode(array $params)
    {
        Db::beginTransaction();
        try {
            $data = $this->handleData($params);
            $this->syncRobotAddNumbers($data);
            $codeId = $this->save($data);
            if (!$codeId) {
                throw new NormalStatusException('保存失败');
            }
            $code = $this->mapper->findById($codeId);
            $enableRobotInfo = $this->getEnableRobotInfo($code, Carbon::now());
            if (empty($enableRobotInfo['robotIds'])) {
                throw new NormalStatusException('请选择机器人');
            }
            //创建渠道码
            $codeInfo = $this->getContactWay($enableRobotInfo['robotIds'], $code);
            $qr_code=$codeInfo['qr_code'];
            if(!empty($params['logo'])){
                $qr_code=$this->setLogoToImages($qr_code,$params['logo'])['url'];
            }
            $this->mapper->update($codeId, [
                'code' => $qr_code,
                'render_url' => '',
                'extend' => ['config_id' => $codeInfo['config_id']],
                'next_refresh_time' => $enableRobotInfo['nextRefreshTime']
            ]);
            //记录日志
            event((new ChOperationLog(
                (new OperationLogDto())
                    ->setUid($params['uid'])
                    ->setMainUid($params['main_uid'])
                    ->setSchemeId($codeId)
                    ->setName($data['channel_name'])
                    ->setContent('新建渠道活码')
                    ->setType(OperatorLogConstants::CHANNEL_CODE)
            )));
            Db::commit();
            return $codeId;
        } catch (\Throwable $ex) {
            Db::rollBack();
            throw new BusinessException((int)$ex->getCode(), $ex->getMessage());
        }
    }

    public function updateChannelCode(array $params): bool
    {
        Db::beginTransaction();
        try {
            $codeId = $params['code_id'];
            $data = $this->handleData($params);

            $this->syncRobotAddNumbers($data);

            co(function () use ($codeId) {
                //清除二维码缓存
                $this->deleteChannelCodeCacheSafely($codeId);
            });
            $this->mapper->update($data['code_id'], $data);
            $code = $this->mapper->model::find($codeId);
            $enableRobotInfo = $this->getEnableRobotInfo($code, Carbon::now());
            if (empty($enableRobotInfo['robotIds'])) {
                throw new NormalStatusException('请选择机器人');
            }
            //创建渠道码
            $this->upContactWay($enableRobotInfo['robotIds'], $code);
            $data['next_refresh_time']=$enableRobotInfo['nextRefreshTime'];
            $qr_code=$code['code'];
            if(!empty($params['logo'])){
                $qr_code=$this->setLogoToImages($qr_code,$params['logo'])['url'];
                $data['code']=$qr_code;
            }
            $this->mapper->update($data['code_id'], $data);
            event((new ChOperationLog(
                (new OperationLogDto())
                    ->setUid($params['uid'])
                    ->setMainUid($params['main_uid'])
                    ->setSchemeId((int)$codeId)
                    ->setName($data['channel_name'])
                    ->setContent('编辑渠道活码')
                    ->setType(OperatorLogConstants::CHANNEL_CODE)
            )));
            Db::commit();
            return true;
        } catch (\Throwable $ex) {
            Db::rollBack();
            throw new BusinessException((int)$ex->getCode(), $ex->getMessage());
        }
    }

    public function deleteChannelCode(array $params): bool
    {
        $id = $params['id'];
        $code=$this->mapper->findById($id);
        if(!empty($code->extend['config_id'])){
            $corpInfo = container()->get(ChCorpMapper::class)->findById($code->corp_id);
            if (empty($corpInfo['auth_corp_id'])) {
                throw new NormalStatusException('请先授权');
            }
            $OpenWorkService = new OpenWorkService($corpInfo['auth_corp_id']);
            $OpenWorkService->deleteContactWay(['config_id'=>$code->extend['config_id']]);
        }
        return $this->mapper->delete([$id]);
    }

    public function getEnableRobotByCodeId($codeId): array
    {
        $datetime = Carbon::now();
        $code = $this->mapper->model::find($codeId)->first();

        // 获取实时添加数
        $robotAddNumbers = $this->robotAddNumberMapper->model::query()
            ->whereIn('robot_id', $this->extractAllRobotIds($code->toArray()))
            ->pluck('add_number', 'robot_id')
            ->toArray();

        return $this->calculateEnableRobots($code, $datetime, $robotAddNumbers);
    }

    public function getCodeDetail(array $params): object
    {
        // 1. 获取基础数据
        $codeId = (int)($params['id'] ?? 0);
        $code = $this->mapper->model::query()->with(['user' => function ($q) {
            $q->select('id', 'nickname', 'avatar');
        }])->find($codeId);

        if (!$code) {
            throw new NormalStatusException('未找到链接');
        }

        // 2. 提取所有相关机器人ID
        $robotIds = $this->extractAllRobotIds($code->toArray());

        // 3. 批量获取机器人信息
        $robotsMap = $this->getRobotsMap($robotIds);

        // 4. 注入机器人信息到配置字段
        $this->injectRobotInfos($code, $robotsMap);

        return $code;
    }

    public function getChannelCodeData(array $params): object
    {
        $uid = (int)($params['uid'] ?? 0);
        $codeId = (string)($params['code_id'] ?? 0);
        return $this->codeRecordMapper->getCodeStatisticsByCodeIdAndCodeId($uid, $codeId);
    }

    public function getChannelCodeDailyData(array $params): array
    {
        $uid = (int)($params['uid'] ?? 0);
        $codeId = (string)($params['code_id'] ?? 0);
        $pageSize = (int)($params['page_size'] ?? 10);
        $query = $this->codeRecordMapper->getDailyCodeStatisticsByUidAndCodeId($uid, $codeId);
        $paginator = $query->paginate($pageSize);
        return $this->mapper->setPaginate($paginator);
    }

    public function getChannelCodeRobotData(array $params)
    {
        $uid = (int)($params['uid'] ?? 0);
        $codeId = (string)($params['code_id'] ?? 0);
        $pageSize = (int)($params['page_size'] ?? MineModel::PAGE_SIZE);
        $statistics = $this->codeRecordMapper->getRobotCodeStatisticsByUidAndCodeId($uid, $codeId)
            ->join('ch_robot', 'ch_channel_code_record.robot_id', '=', 'ch_robot.id')
            ->select([
                'ch_channel_code_record.robot_id',
                'ch_robot.nickname as robot_nickname',
                'ch_robot.avatar as robot_avatar',
                Db::raw('COUNT(*) AS daily_count'),
                Db::raw('COUNT(CASE WHEN ch_channel_code_record.is_remain = 1 THEN 1 END) AS remained_count')
            ])
            // 修复点：明确所有字段的来源表
            ->groupBy(
                'ch_channel_code_record.robot_id',
                'ch_robot.nickname',
                'ch_robot.avatar'
            );

        $paginate = $statistics->paginate($pageSize);
        return $this->mapper->setPaginate($paginate);
    }

    public function addTask($robotId, $contactId, $code, bool $isExist): void
    {


        Db::transaction(function () use ($code, $robotId, $isExist, $contactId) {
            // 1. 获取渠道码信息

            // 2. 写入添加记录
            $this->codeRecordMapper->model::create([
                'uid' => $code->uid,
                'main_uid' => $code->main_uid, // 使用渠道码主账号
                'code_id' => $code->id,
                'robot_id' => $robotId,
                'contact_id' => $contactId,
                'is_remain' => 1, // 默认留存
                'is_new' => $isExist ? 0 : 1, // 根据参数判断是否新客
            ]);

            // 3. 更新机器人添加数（原子操作）
            $this->robotAddNumberMapper->model::updateOrCreate(
                ['robot_id' => $robotId],
                ['add_number' => Db::raw('add_number + 1')]
            );
        });
    }

    public function changeLogStatus($contactId): void
    {
        $this->changeLogMapper->model::where('contact_id', $contactId)->update(['is_remain' => 0]);
    }

    public function getChannelCodeReport($params)
    {
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;
        $uid = (int)$params['uid'];
        $codeIds = explode(',', $params['code_ids']) ?? [];
        $timeType = (int)($params['time_type'] ?? 0);
        $channelName = $params['channel_name'] ?? null;
        // 获取查询构建器和日期标签
        $reportData = $this->codeRecordMapper->getChannelReport($uid, $codeIds, $timeType, $channelName);

        // 分页处理
        $paginator = $reportData->paginate($pageSize);
        return $this->mapper->setPaginate($paginator);
    }

    public function exportChannelCodeReport(array $params, ?string $dto, ?string $filename = null, ?\Closure $callbackData = null): ResponseInterface
    {
        $uid = (int)$params['uid'];
        $codeIds = explode(',', $params['code_ids']) ?? [];
        $timeType = (int)($params['time_type'] ?? 0);
        $channelName = $params['channel_name'] ?? null;
        if (empty($dto)) {
            return container()->get(MineResponse::class)->error('导出未指定DTO');
        }

        // 动态生成文件名
        $timeTypeMap = [
            0 => '单日',
            1 => '近一周',
            2 => '近两周',
            3 => '近一月'
        ];
        $timeLabel = $timeTypeMap[$timeType] ?? '未知时段';

        if (empty($filename)) {
            $filename = "渠道活码（{$timeLabel}）数据报表_" . Carbon::now()->format('Y-m-d_H-i-s') . ".xlsx";
        }

        $query = $this->codeRecordMapper->getChannelReport($uid, $codeIds, $timeType, $channelName);

        $list = $query->get();

        // 执行导出
        return (new MineCollection())->export($dto, $filename, $list->toArray(), $callbackData);
    }

    public function getChannelCodeReportDetail(array $params)
    {
        $uid = (int)$params['uid'];
        $codeIds = explode(',', $params['code_ids']) ?? [];
        $timeType = (int)($params['time_type'] ?? 0);
        $channelName = $params['channel_name'] ?? null;
        return $this->codeRecordMapper->getChannelReportDetail($uid, $codeIds, $timeType, $channelName);
    }

    public function addTagsAndRemark($contact, $code)
    {
        $data = [];

        //提取智能标签和企业标签ID
        $smartTagIds = $this->extractTagIds(data_get($code, 'auto_tags.tags.smart_tags', []));
        $corpTagIds = $this->extractTagIds(data_get($code, 'auto_tags.tags.corp_tags', []));

        $contactService = container()->get(ChContactService::class);

        // 处理智能标签
        if (!empty($smartTagIds)) {
            $data['id'] = $contact->id;
            $data['smart_tag_ids'] = json_encode($smartTagIds);
            $data['type'] = 0;
            $contactService->setSmartTag($data);
        }

        // 处理企业标签
        if (!empty($corpTagIds)) {
            $data['id'] = $contact->id;
            $data['corp_tag_ids'] = json_encode($corpTagIds);
            $contactService->setCorpTag($data);
        }

    }

    /**
     * 从渠道码对象中提取所有robot_ids
     */
    private function extractAllRobotIds(array $code): array
    {
        $configPaths = [
            'spare_robot_ids',
            'all_day_display_cfg.robot_ids',
            'time_segment_cfg.time_segment_cfg.*.robot_ids', // 修正嵌套路径
            'daily_add_friend_cfg.daily_add_friend_cfg.*.robot_ids',
            'special_member_greeting_cfg.special_member_greeting_cfg.*.robot_ids' // 匹配实际数据结构
        ];

        $robotIds = [];
        foreach ($configPaths as $path) {
            $values = data_get($code, $path, []);

            // 处理多维嵌套
            $values = Arr::flatten((array)$values);

            // 强化类型过滤
            $values = array_map('intval', $values);
            $values = array_filter($values, fn($id) => $id > 0);

            $robotIds = array_merge($robotIds, $values);
        }

        return array_values(array_unique($robotIds));

    }

    /**
     * 批量获取机器人信息映射表
     */
    private function getRobotsMap(array $robotIds): array
    {
        if (empty($robotIds)) {
            return [];
        }

        // 只获取必要字段
        $fields = 'id,nickname,avatar';
        $robots = $this->robotMapper->findByIds($robotIds, $fields);

        return collect($robots)->keyBy('id')->all();
    }

    /**
     * 将机器人信息注入到code对象
     */
    private function injectRobotInfos(object $code, array $robotsMap): void
    {
        $fields = [
            'all_day_display_cfg' => ['robot_ids'],
            'time_segment_cfg' => ['time_segment_cfg.*.robot_ids'],
            'daily_add_friend_cfg' => ['daily_add_friend_cfg.*.robot_ids'],
            'spare_robot_ids' => ['robot_ids'],
            'special_member_greeting_cfg' => ['special_member_greeting_cfg.*.robot_ids']
        ];

        foreach ($fields as $field => $paths) {
            if (!empty($code->$field)) {
                $config = (array)$code->$field;
                foreach ($paths as $path) {
                    $items = data_get($config, $path, []);
                    foreach ($items as $index => $item) {
                        if (isset($item['robot_ids'])) {
                            data_set($config, "{$path}.{$index}.robot_infos",
                                $this->mapRobotInfos($item['robot_ids'], $robotsMap)
                            );
                        }
                    }
                }
                $code->$field = $config;
            }
        }
    }

    /**
     * 将机器人信息注入到配置数组
     */
    private function injectInfoToConfig(array $config, array $robotsMap): array
    {
        // 处理直接路径
        foreach ($this->configHandlers['direct']['paths'] as $path) {
            if ($data = data_get($config, $path)) {
                data_set($config, "robot_infos", $this->mapRobotInfos($data, $robotsMap));
            }
        }

        // 处理嵌套路径
        foreach ($this->configHandlers['nested']['paths'] as $path) {
            $items = data_get($config, $path) ?? [];
            foreach ($items as $index => &$item) {
                if ($robotIds = data_get($item, 'robot_ids')) {
                    data_set($item, 'robot_infos', $this->mapRobotInfos($robotIds, $robotsMap));
                }
            }
            data_set($config, $path, $items);
        }

        return $config;
    }

    // 公共的机器人信息映射方法
    private function mapRobotInfos(array $robotIds, array $robotsMap): array
    {
        return array_map(fn($id) => $robotsMap[$id] ?? null, $robotIds);
    }


    private function handleData(array $data)
    {
        $keysToDecode = [
            "auto_tags",
            "all_day_display_cfg",
            "spare_robot_ids",
            "time_segment_cfg",
            "daily_add_friend_cfg",
            "default_greeting_cfg",
            "time_segment_greeting_cfg",
            "special_member_greeting_cfg"
        ];

        foreach ($keysToDecode as $key) {
            if (empty($data[$key])) $data[$key] = null;
            if (isset($data[$key]) && is_string($data[$key])) {
                $decoded = json_decode($data[$key], true);
                if ($decoded !== null) {
                    $data[$key] = $decoded;
                }
            }
        }
        return $data;
    }

    /**
     * 添加机器人信息
     */
    private function syncRobotAddNumbers(array $codeData): void
    {
        // 1. 提取所有robot_ids
        $robotIds = $this->extractAllRobotIds($codeData);

        if (empty($robotIds)) return;

        // 2. 查询已存在的robot_id
        $exists = $this->robotAddNumberMapper->existRobotIds($robotIds);

        // 3. 过滤需要新增的robot_id
        $newIds = array_diff($robotIds, $exists);

        // 4. 批量插入新记录
        if (!empty($newIds)) {
            $insertData = array_map(function ($robotId) {
                return [
                    'robot_id' => $robotId,
                    'add_number' => 0,
                ];
            }, $newIds);

            $this->robotAddNumberMapper->model::insert($insertData);
        }
    }

    /**
     * 获取机器人信息
     */
    private function getRobotData(array $robotIds): ?array
    {
        if (empty($robotIds)) return null;

        // 批量获取机器人信息（新增login_status字段）
        $collection = $this->robotMapper->findByIds(
            $robotIds,
            'id,nickname,login_status'
        );

        $robots = $collection instanceof MineCollection
            ? $collection->toArray()
            : (array)$collection;

        return array_map(function ($robot) {
            return [
                'id' => $robot['id'],
                'nickname' => $robot['nickname'],
                'login_status' => $robot['login_status']
            ];
        }, $robots);
    }

    /**
     * 添加活码修改记录
     */
    private function recordChangeLog(int $uid, int $mainUid, string $changedFields): void
    {
        $fieldMap = [
            'channel_name' => '渠道名称',
            'auto_verify' => '自动验证开关',
            'auto_tags' => '标签组',
            'auto_remark' => '自动备注开关',
            'remark_content' => '备注配置',
            'display_mode' => '展示方式',
            'all_day_display_cfg' => '全天展示配置',
            'time_segment_cfg' => '分时段配置',
            'daily_add_friend_limit' => '加好友限制',
            'daily_add_friend_cfg' => '限制配置',
            'spare_robot_ids' => '备用机器人',
            'default_greeting_cfg' => '默认欢迎语',
            'time_segment_greeting' => '分时段欢迎语开关',
            'time_segment_greeting_cfg' => '分时段欢迎语配置',
            'special_member_greeting' => '特殊成员欢迎语开关',
            'special_member_greeting_cfg' => '特殊成员欢迎语配置',
            'code_style' => '活码样式',
        ];;
        $changedArray = explode(',', $changedFields);

        $logItems = [];
        foreach ($changedArray as $field) {
            if (isset($fieldMap[$field])) {
                $logItems[] = $fieldMap[$field];
            }
        }

        if (!empty($logItems)) {
            $this->changeLogMapper->model::create([
                'uid' => $uid,
                'main_uid' => $mainUid,
                'edit_details' => '修改了：' . implode('、', $logItems),
                'created_at' => Carbon::now()
            ]);
        }
    }

    /**
     * 过滤超过限制的机器人
     */
    private function filterExceededRobots(array $robotIds, int $maxAddNumber): array
    {
        if (empty($robotIds) || $maxAddNumber <= 0) {
            return $robotIds;
        }

        $addNumbers = $this->robotAddNumberMapper->model::query()
            ->whereIn('robot_id', $robotIds)
            ->pluck('add_number', 'robot_id')
            ->toArray();

        return array_values(array_filter($robotIds, function ($robotId) use ($addNumbers, $maxAddNumber) {
            $current = $addNumbers[$robotId] ?? 0;
            return $current < $maxAddNumber;
        }));
    }

    /**
     * 获取打招呼内容
     */
    private function getGreetingContent($codeId, int $robotId)
    {
        $code = $this->mapper->model::find($codeId)->first();
        $spareRobotIds = $code->spare_robot_ids ?? [];
        $now = Carbon::now();
        $greeting = data_get($code, 'default_greeting_cfg', []);

        if ($code->time_segment_greeting === 1) {
            $cfg = data_get($code, 'time_segment_greeting_cfg.time_segment_greeting_cfg', []);
            $currentWeekDay = (int)$now->format('N'); // 1=周一...7=周日
            $currentTime = $now->format('H:i');

            foreach ($cfg as $group) {
                $start = Carbon::parse($group['time'][0])->format('H:i');
                $end = Carbon::parse($group['time'][1])->format('H:i');
                $timeCondition = $start > $end
                    ? ($currentTime >= $start || $currentTime <= $end)
                    : ($currentTime >= $start && $currentTime <= $end);

                if (in_array($currentWeekDay, $group['week'], true) && $timeCondition) {
                    $greeting = data_get($group, 'greeting', []);
                }
            }
        }
        if ($code->special_member_greeting === 1) {
            $cfg = data_get($code, 'special_member_greeting_cfg.special_member_greeting_cfg', []);

            foreach ($cfg as $group) {
                $robotIds = array_map('intval', (array)data_get($group, 'robot_ids', []));

                if (in_array($robotId, $robotIds, true)) {
                    $greeting = data_get($group, 'greeting', []);
                }
            }
        }
        return $greeting;
    }

    /**
     * 根据机器人ID和用户ID查找匹配的渠道码
     * @param int $robotId 机器人ID
     * @param int $uid 用户ID
     * @return object|null
     */
    public function findCodeByRobotIdAndUid(int $robotId, int $uid): object|null
    {
        $result = null;
        // 1. 获取用户所有渠道码基础数据
        $codes = $this->mapper->model::query()
            ->where('uid', $uid)
            ->select()
            ->get()
            ->each(function ($code) {
                // 动态计算robot_ids字段
                $code->robot_ids = $this->extractAllRobotIds($code->toArray());
            });

        if ($codes->isEmpty()) {
            return null;
        }

        // 2. 批量预加载机器人添加数
        $allRobotIds = $codes->pluck('robot_ids')->flatten()->unique()->toArray();
        $robotAddNumbers = $this->robotAddNumberMapper->model::query()
            ->whereIn('robot_id', $allRobotIds)
            ->pluck('add_number', 'robot_id')
            ->toArray();

        // 3. 实时计算并匹配
        $now = Carbon::now();
        foreach ($codes as $code) {
            $enableRobotIds = $this->calculateEnableRobots($code, $now, $robotAddNumbers);
            if (in_array($robotId, $enableRobotIds, true)) {
                $result = $code;
            }
        }

        // 第二阶段：匹配备用机器人（新增逻辑）
        foreach ($codes as $code) {
            $spareRobotIds = data_get($code, 'spare_robot_ids.robot_ids', []);
            if (in_array($robotId, $spareRobotIds, true)) {
                // 验证备用机器人有效性
                $result = $code;
            }
        }

        return $result;
    }

    public function getQrCode(string $codeId): string
    {
        // 1. 获取渠道码信息
        $codeObject = $this->mapper->findById($codeId);
        if (!$codeObject) {
            throw new NormalStatusException('该链接已被删除');
        }

        // 2. 合并可用机器人和备用机器人ID（去重）
        $enableRobotIds = $this->getEnableRobotByCodeId($codeObject->id);
        $spareRobotIds = $codeObject->spare_robot_ids['robot_ids'] ?? [];
        $allRobotIds = array_unique(array_merge($enableRobotIds, $spareRobotIds));

        if (empty($allRobotIds)) {
            throw new NormalStatusException('该链接无客服');
        }

        // 3. 批量获取机器人状态和添加数信息
        $robots = $this->robotMapper->findByIds(
            $allRobotIds,
            'id,nickname,login_status'
        )->map(function ($robot) {
            // 获取每个机器人的添加次数
            $robot->add_number = $this->robotAddNumberMapper->model::query()
                ->where('robot_id', $robot->id)
                ->value('add_number') ?? 0;
            return $robot;
        });

        // 4. 分类和排序逻辑优化
        $priorityGroups = [
            'available_online' => collect(),
            'spare_online' => collect(),
            'others' => collect()
        ];

        foreach ($robots as $robot) {
            $isAvailable = in_array($robot->id, $enableRobotIds, true);
            $isSpare = in_array($robot->id, $spareRobotIds, true);

            if ($robot->login_status == 1) {
                if ($isAvailable) {
                    $priorityGroups['available_online']->push($robot);
                } elseif ($isSpare) {
                    $priorityGroups['spare_online']->push($robot);
                }
            } else {
                $priorityGroups['others']->push($robot);
            }
        }

        // 5. 新增备用机器人排序逻辑（按添加数升序）
        $priorityGroups['spare_online'] = $priorityGroups['spare_online']->sortBy('add_number');
        $priorityGroups['others'] = $priorityGroups['others']->sortBy('add_number');

        // 6. 按新优先级选择机器人组
        foreach (['available_online', 'spare_online', 'others'] as $group) {
            if ($priorityGroups[$group]->isNotEmpty()) {
                // 只选择在线机器人
                foreach ($priorityGroups[$group] as $robot) {
                    if ($robot->login_status == 1) {
                        $selectedRobot = $robot;
                        $robotService = container()->get(ChRobotService::class);
                        return $robotService->getPersonalQRCode(['id' => $selectedRobot->id]);
                    }
                }
            }
        }

        throw new NormalStatusException('该链接暂无可用客服');
    }

    /**
     * 核心计算逻辑：获取渠道码当前生效的机器人ID
     * @param object $code 渠道码数据对象
     * @param DateTimeInterface $datetime 当前时间
     * @param array $robotAddNumbers 预加载的机器人添加数 [robot_id => add_number]
     * @return array
     */
    private function calculateEnableRobots(ChChannelCode $code, DateTimeInterface $datetime, array $robotAddNumbers = []): array
    {
        // 阶段1：获取基础机器人ID
        $robotIds = match ((int)$code->display_mode) {
            0 => data_get($code->all_day_display_cfg, 'robot_ids', []),
            1 => $this->getTimeSegmentRobots($code, $datetime),
            default => []
        };

        // 阶段2：应用添加限制
        return match ((int)$code->daily_add_friend_limit) {
            1 => $this->applyGlobalLimit($robotIds, $code, $robotAddNumbers),
            2 => $this->applyGroupLimit($robotIds, $code, $robotAddNumbers),
            default => $robotIds
        };
    }

    /**
     * 分时段模式机器人计算
     */
    private function getTimeSegmentRobots(object $code, DateTimeInterface $datetime): array
    {
        $currentWeekDay = (int)$datetime->format('N');
        $currentTime = $datetime->format('H:i');
        $robotIds = [];

        foreach (data_get($code, 'time_segment_cfg', []) as $segment) {
            // 星期匹配检查
            if (!in_array($currentWeekDay, $segment['week'] ?? [])) {
                continue;
            }

            // 时间段处理（支持跨天）
            $start = Carbon::parse($segment['time'][0])->format('H:i');
            $end = Carbon::parse($segment['time'][1])->format('H:i');
            $timeCondition = ($start > $end)
                ? ($currentTime >= $start || $currentTime <= $end)
                : ($currentTime >= $start && $currentTime <= $end);

            if ($timeCondition) {
                $robotIds = array_merge($robotIds, (array)($segment['robot_ids'] ?? []));
            }
        }

        return array_unique(array_map('intval', $robotIds));
    }

    private function getAllTimeSegmentRobots(object $code, DateTimeInterface $datetime): array
    {
        $currentWeekDay = (int)$datetime->format('N');
        $currentTime = $datetime->format('H:i');
        $robotIds = [];

        foreach (data_get($code, 'time_segment_cfg', []) as $segment) {
            // 星期匹配检查
            $robotIds = array_merge($robotIds, (array)($segment['robot_ids'] ?? []));
        }

        return array_unique(array_map('intval', $robotIds));
    }

    /**
     * 应用全局添加限制
     */
    private function applyGlobalLimit(array $robotIds, object $code, array $robotAddNumbers): array
    {
        $daily_add_friend_cfg = data_get(
            $code,
            'daily_add_friend_cfg.daily_add_friend_cfg',
            0
        );
        $globalLimit = $daily_add_friend_cfg[0]['limit'];
        $robotIds = array_values(array_filter(
            $robotIds,
            fn($id) => ($robotAddNumbers[$id] ?? 0) < $globalLimit || $globalLimit == 0
        ));
        //todo  备用机器人
        if (!empty($daily_add_friend_cfg[0]['robot_ids']) && empty($robotIds)) {
            $robotIds = $daily_add_friend_cfg[0]['robot_ids'];
        }
        return $robotIds;
    }

    /**
     * 应用分组添加限制
     */
    private function applyGroupLimit(array $robotIds, object $code, array $robotAddNumbers): array
    {
        $groupCfgs = data_get($code, 'daily_add_friend_cfg.daily_add_friend_cfg', []);
        $otherGroupCfgs = data_get($code, 'daily_add_friend_cfg.other_cfg', []);
        //已经处理的ids
        $allGroupIds = [];
        //符合条件的ids
        $validRobotIds = [];
        foreach ($groupCfgs as $group) {
            $groupRobotIds = data_get($group, 'robot_ids', []);
            $allGroupIds = array_merge($allGroupIds, $groupRobotIds);
            $limit = (int)data_get($group, 'limit', 0);
            //符合条件的id
            $groupRobotIds = array_filter(
                $groupRobotIds,
                fn($id) => ($robotAddNumbers[$id] ?? 0) < $limit || $limit == 0
            );
            $validRobotIds = array_merge($validRobotIds, $groupRobotIds);
        }
        //其他未处理的机器人
        $otherRobotIds = array_diff($robotIds, $allGroupIds);
        if (!empty($otherRobotIds) && !empty($otherGroupCfgs)) {
            $otherRobotIds = array_filter(
                $otherRobotIds,
                fn($id) => ($robotAddNumbers[$id] ?? 0) < $otherGroupCfgs['limit'] || $otherGroupCfgs['limit'] == 0
            );
            $validRobotIds = array_merge($validRobotIds, $otherRobotIds);
        }
        return $validRobotIds;
    }

    private function extractTagIds(array $tags): array
    {
        return array_values(array_filter(array_map(function ($tag) {
            return $tag['id'] ?? null;
        }, $tags)));
    }

    /**
     * 获取客服二维码
     * @param mixed $robotId
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function getContactWay(mixed $robotIds, mixed $code)
    {
        try {
//            $cacheName = $this->cachePrefix.$code->id.":".md5("contactWay".$code->id);
//            $qrCache = $this->redis->get($cacheName);
//            if(!empty($qrCache)){
//                return $qrCache;
//            }
            $corpInfo = container()->get(ChCorpMapper::class)->findById($code->corp_id);
            if (empty($corpInfo['auth_corp_id'])) {
                throw new NormalStatusException('请先授权');
            }
            $openUserIds = [];
            foreach ($robotIds as $robotId) {
                $robot = $this->robotMapper->findById($robotId);
                $robotUserId = $robot['user_id'];
                if (!empty($robot['userid'])) {
                    $openUserid = $robot['userid'];
                } else {
                    $RobotApiService = make(Robot::class, [$robot->server_id, $robot->uuid])->gateway();
                    $response = $RobotApiService->getProfile();
                    if($response === false){
                        continue;
                    }
                    $acctid = $response['acctid'];
                    $response = make(OpenWorkService::class,[$corpInfo->auth_corp_id])->getOpenUserid([$acctid]);
                    if($response === false){
                        continue;
                    }
                    $openUserid = $response['open_userid_list'][0]['open_userid'];
                    $this->robotMapper->update($robotId, ['userid' => $openUserid]);

                }
//                $RobotApiService = make(Robot::class, [$robot->server_id, $robot->uuid])->gateway();
//                $response = $RobotApiService->getProfile();
//                if($response === false){
//                    continue;
//                }
//                $acctid = $response['acctid'];
//                $response = make(OpenWorkService::class,[$corpInfo->auth_corp_id])->getOpenUserid([$acctid]);
//                if($response === false){
//                    continue;
//                }
//                $openUserid = $response['open_userid_list'][0]['open_userid'];
//                $this->robotMapper->update($robotId, ['userid' => $openUserid]);
                $openUserIds[] = $openUserid;
            }

            $dto = (new AddContactWayDto())
                ->setType(2)
                ->setScene(2)
                ->setState('type=1&code=' . $code->id)
                ->setUser($openUserIds);
            if ($code->auto_verify) {
                $dto->setSkipVerify(1);
            }
            $OpenWorkService = new OpenWorkService($corpInfo['auth_corp_id']);
            $codeInfo = $OpenWorkService->addContactWay($dto);
            return $codeInfo;
            //$this->redis->set($cacheName,$codeInfo['qr_code'],7*24*3600);
        } catch (\Exception $e) {
            throw new NormalStatusException($e->getMessage());
        }
    }


    public function upContactWay(mixed $robotIds, mixed $code)
    {
        try {
//            $cacheName = $this->cachePrefix.$code->id.":".md5("contactWay".$code->id);
//            $qrCache = $this->redis->get($cacheName);
//            if(!empty($qrCache)){
//                return $qrCache;
//            }
            $corpInfo = container()->get(ChCorpMapper::class)->findById($code->corp_id);
            if (empty($corpInfo['auth_corp_id'])) {
                throw new NormalStatusException('请先授权');
            }
            $openUserIds = [];
            foreach ($robotIds as $robotId) {
                $robot = $this->robotMapper->findById($robotId);
                $robotUserId = $robot['user_id'];
                if (!empty($robot['userid'])) {
                    $openUserid = $robot['userid'];
                } else {
                    $RobotApiService = make(Robot::class, [$robot->server_id, $robot->uuid])->gateway();
                    $response = $RobotApiService->getProfile();
                    if($response === false){
                        continue;
                    }
                    $acctid = $response['acctid'];
                    $response = make(OpenWorkService::class,[$corpInfo->auth_corp_id])->getOpenUserid([$acctid]);
                    if($response === false){
                        continue;
                    }
                    $openUserid = $response['open_userid_list'][0]['open_userid'];
                    $this->robotMapper->update($robotId, ['userid' => $openUserid]);
                }
//                $RobotApiService = make(Robot::class, [$robot->server_id, $robot->uuid])->gateway();
//                $response = $RobotApiService->getProfile();
//                if($response === false){
//                    continue;
//                }
//                $acctid = $response['acctid'];
//                $response = make(OpenWorkService::class,[$corpInfo->auth_corp_id])->getOpenUserid([$acctid]);
//                if($response === false){
//                    continue;
//                }
//                $openUserid = $response['open_userid_list'][0]['open_userid'];
//                $this->robotMapper->update($robotId, ['userid' => $openUserid]);
                $openUserIds[] = $openUserid;
            }


            $dto = (new AddContactWayDto())
                ->setType(2)
                ->setScene(2)
                ->setConfigId($code->extend['config_id'])
                ->setState('type=1&code=' . $code->id)
                ->setUser($openUserIds);
            if ($code->auto_verify) {
                $dto->setSkipVerify(1);
            }
            $OpenWorkService = new OpenWorkService($corpInfo['auth_corp_id']);
            $codeInfo = $OpenWorkService->updateContactWay($dto);
            return $codeInfo;
            //$this->redis->set($cacheName,$codeInfo['qr_code'],7*24*3600);
        } catch (\Exception $e) {
            throw new NormalStatusException($e->getMessage());
        }
    }

    public function deleteChannelCodeCacheSafely($codeId)
    {
        $key = $this->cachePrefix . $codeId . "*";
        $keys = make(RedisCluster::class)->scan($key);
        $this->redis->del($keys);
    }

    public function setLogoToImages($imgUrl,$logoUrl):mixed
    {
        try {
            $fileName = Random::generate(20).'.png';
            $directory    = BASE_PATH . '/public/uploadfile';
            if (!is_dir($directory)) {
                mkdir($directory, 0755, true);
            }
            $result=container()->get(ImageHelp::class)->addLogoToImage(
                $imgUrl,
                $logoUrl,
                $directory."/".$fileName
            );
            if(!$result){
                throw new NormalStatusException('图片处理失败');
            }
            $imageContent = file_get_contents($directory."/".$fileName);
            $url = container()->get(CommonUpload::class)->setStorageMode(StorageModeConstants::OSS)->uploadWrite($imageContent,'');
            unlink($directory."/".$fileName);
            return ['url'=>config('file.storage.oss.domain','').$url];
        }catch (\Exception $e){
            logger()->info("渠道码logo处理失败:".$e->getMessage());
            return false;
        }
    }
}